Skip to content

feat(ramps-controller)!: source widened Headless Buy default redirect URL from RampsService - #9752

Merged
saustrie-consensys merged 4 commits into
mainfrom
tram-3757-redirect-url
Aug 3, 2026
Merged

feat(ramps-controller)!: source widened Headless Buy default redirect URL from RampsService#9752
saustrie-consensys merged 4 commits into
mainfrom
tram-3757-redirect-url

Conversation

@saustrie-consensys

@saustrie-consensys saustrie-consensys commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Explanation

On the widened Headless Buy all-providers path, MetaMask Pay's quote request omits redirectUrl. The quotes API only embeds a buyURL/buyWidget when a redirectUrl is present, so RampsController.getQuotes must supply a default there. Until now that default came from a getDefaultRedirectUrl callback injected by the mobile client, which review flagged as an unusual controller-init pattern for a value core can derive itself.

This PR moves ownership into core without giving RampsController a second copy of the environment:

  • Adds the exported pure getDefaultRedirectCallbackUrl(environment) helper as the canonical environment-to-callback map (on-ramp-content for production/staging, on-ramp.dev-api for development, localhost:3000 for local).
  • Adds RampsService.getDefaultRedirectCallbackUrl() and the matching messenger action, which returns that URL for the environment the service was already constructed with. baseUrlOverride deliberately does not apply: in production and staging the callback lives on on-ramp-content, not the API/on-ramp-cache host that baseUrlOverride replaces; using the API override here would break client completion matching. RampsEnvironment.Local yields a localhost callback pinned to port 3000.
  • Removes getDefaultRedirectUrl from RampsControllerOptions. On the widened path, when the caller omits redirectUrl, the controller calls RampsService:getDefaultRedirectCallbackUrl. Explicit caller redirectUrl still wins; the native-only (flag-off) path still injects nothing.

If a host upgrades without delegating the new action, the entire RampsController:getQuotes call rejects (including MM Pay fiat quoting), rather than returning aggregator quotes without a widget URL. That is intentional and covered by a unit test.

Breaking change

  1. Delegate RampsService:getDefaultRedirectCallbackUrl to the RampsController messenger (prefer spreading RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS instead of extending a hand-written list), and drop any getDefaultRedirectUrl constructor argument.
  2. Reimplement mobile getRampCallbackBaseUrl() as getDefaultRedirectCallbackUrl(getRampsEnvironment()) in the same upgrade so quote defaults and Checkout completion detection share one environment source. Builds that set RAMPS_ENVIRONMENT differently from METAMASK_ENVIRONMENT (notably some exp / e2e-bs flavors) can otherwise mismatch.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Breaking messenger and constructor contract for Headless Buy / MM Pay quoting; mis-delegation fails the whole getQuotes call, and env mismatch between service and UI callback detection could break checkout completion.

Overview
Breaking: Widened Headless Buy quotes no longer use an injected getDefaultRedirectUrl on RampsController. When moneyHeadlessAllProviders is on and the caller omits redirectUrl, the controller calls RampsService:getDefaultRedirectCallbackUrl and forwards that URL into getQuotes so aggregator quotes get a buyURL/buyWidget. Explicit redirectUrl still wins; the native-only path does not call the service.

Adds getDefaultRedirectCallbackUrl(environment) (canonical env → /regions/fake-callback map, ignoring baseUrlOverride) plus RampsService.getDefaultRedirectCallbackUrl() and the messenger action/type, exported from the package. Hosts must delegate the new action (listed in RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS) or getQuotes rejects; mobile should align UI callback matching with the same helper and environment source.

Reviewed by Cursor Bugbot for commit 3b3ff32. Bugbot is set up for automated code reviews on this repo. Configure here.

@saustrie-consensys saustrie-consensys changed the title feat(ramps-controller)!: derive widened Headless Buy default redirect URL from environment feat(ramps-controller)!: source widened Headless Buy default redirect URL from RampsService Aug 3, 2026
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-ea0a8c22f
@metamask-previews/accounts-controller@39.0.6-preview-ea0a8c22f
@metamask-previews/address-book-controller@7.1.2-preview-ea0a8c22f
@metamask-previews/ai-controllers@0.8.0-preview-ea0a8c22f
@metamask-previews/analytics-controller@2.0.0-preview-ea0a8c22f
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-ea0a8c22f
@metamask-previews/announcement-controller@8.1.0-preview-ea0a8c22f
@metamask-previews/app-metadata-controller@2.0.1-preview-ea0a8c22f
@metamask-previews/approval-controller@9.0.2-preview-ea0a8c22f
@metamask-previews/assets-controller@13.1.0-preview-ea0a8c22f
@metamask-previews/assets-controllers@110.1.0-preview-ea0a8c22f
@metamask-previews/authenticated-user-storage@3.0.1-preview-ea0a8c22f
@metamask-previews/base-controller@9.1.0-preview-ea0a8c22f
@metamask-previews/base-data-service@0.1.3-preview-ea0a8c22f
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-ea0a8c22f
@metamask-previews/bridge-controller@78.0.3-preview-ea0a8c22f
@metamask-previews/bridge-status-controller@74.6.1-preview-ea0a8c22f
@metamask-previews/build-utils@3.0.4-preview-ea0a8c22f
@metamask-previews/chain-agnostic-permission@1.7.0-preview-ea0a8c22f
@metamask-previews/chomp-api-service@4.0.0-preview-ea0a8c22f
@metamask-previews/claims-controller@0.5.3-preview-ea0a8c22f
@metamask-previews/client-controller@1.0.1-preview-ea0a8c22f
@metamask-previews/client-utils@1.5.0-preview-ea0a8c22f
@metamask-previews/compliance-controller@2.1.0-preview-ea0a8c22f
@metamask-previews/composable-controller@12.0.1-preview-ea0a8c22f
@metamask-previews/config-registry-controller@2.0.0-preview-ea0a8c22f
@metamask-previews/connectivity-controller@0.3.0-preview-ea0a8c22f
@metamask-previews/controller-utils@12.3.0-preview-ea0a8c22f
@metamask-previews/core-backend@8.1.0-preview-ea0a8c22f
@metamask-previews/delegation-controller@3.0.2-preview-ea0a8c22f
@metamask-previews/earn-controller@12.2.3-preview-ea0a8c22f
@metamask-previews/eip-5792-middleware@3.0.5-preview-ea0a8c22f
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-ea0a8c22f
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-ea0a8c22f
@metamask-previews/ens-controller@19.1.6-preview-ea0a8c22f
@metamask-previews/eth-block-tracker@15.0.1-preview-ea0a8c22f
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-ea0a8c22f
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-ea0a8c22f
@metamask-previews/foundryup@1.0.1-preview-ea0a8c22f
@metamask-previews/gas-fee-controller@26.3.1-preview-ea0a8c22f
@metamask-previews/gator-permissions-controller@5.0.1-preview-ea0a8c22f
@metamask-previews/geolocation-controller@1.0.0-preview-ea0a8c22f
@metamask-previews/java-tron-up@1.0.0-preview-ea0a8c22f
@metamask-previews/json-rpc-engine@10.5.0-preview-ea0a8c22f
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-ea0a8c22f
@metamask-previews/keyring-controller@27.1.0-preview-ea0a8c22f
@metamask-previews/local-node-utils@1.0.0-preview-ea0a8c22f
@metamask-previews/logging-controller@8.0.2-preview-ea0a8c22f
@metamask-previews/message-manager@14.1.2-preview-ea0a8c22f
@metamask-previews/messenger@2.0.0-preview-ea0a8c22f
@metamask-previews/messenger-cli@0.2.0-preview-ea0a8c22f
@metamask-previews/money-account-api-data-service@0.4.0-preview-ea0a8c22f
@metamask-previews/money-account-balance-service@2.4.1-preview-ea0a8c22f
@metamask-previews/money-account-controller@0.3.3-preview-ea0a8c22f
@metamask-previews/money-account-upgrade-controller@3.0.1-preview-ea0a8c22f
@metamask-previews/money-account-utils@1.0.0-preview-ea0a8c22f
@metamask-previews/multichain-account-service@13.0.0-preview-ea0a8c22f
@metamask-previews/multichain-api-middleware@4.0.2-preview-ea0a8c22f
@metamask-previews/multichain-network-controller@3.2.2-preview-ea0a8c22f
@metamask-previews/multichain-transactions-controller@7.1.1-preview-ea0a8c22f
@metamask-previews/name-controller@9.1.2-preview-ea0a8c22f
@metamask-previews/network-connection-banner-controller@0.1.2-preview-ea0a8c22f
@metamask-previews/network-controller@35.0.0-preview-ea0a8c22f
@metamask-previews/network-enablement-controller@6.0.2-preview-ea0a8c22f
@metamask-previews/notification-services-controller@26.0.0-preview-ea0a8c22f
@metamask-previews/passkey-controller@3.0.0-preview-ea0a8c22f
@metamask-previews/permission-controller@13.1.1-preview-ea0a8c22f
@metamask-previews/permission-log-controller@5.1.0-preview-ea0a8c22f
@metamask-previews/perps-controller@10.0.0-preview-ea0a8c22f
@metamask-previews/phishing-controller@17.3.1-preview-ea0a8c22f
@metamask-previews/platform-api-docs@0.0.0-preview-ea0a8c22f
@metamask-previews/polling-controller@16.0.9-preview-ea0a8c22f
@metamask-previews/preferences-controller@23.1.0-preview-ea0a8c22f
@metamask-previews/profile-metrics-controller@4.0.2-preview-ea0a8c22f
@metamask-previews/profile-sync-controller@28.3.0-preview-ea0a8c22f
@metamask-previews/ramps-controller@18.0.1-preview-ea0a8c22f
@metamask-previews/rate-limit-controller@7.0.1-preview-ea0a8c22f
@metamask-previews/react-data-query@0.2.2-preview-ea0a8c22f
@metamask-previews/remote-feature-flag-controller@5.0.0-preview-ea0a8c22f
@metamask-previews/sample-controllers@5.0.4-preview-ea0a8c22f
@metamask-previews/seedless-onboarding-controller@10.1.0-preview-ea0a8c22f
@metamask-previews/selected-network-controller@26.1.6-preview-ea0a8c22f
@metamask-previews/sentinel-api-service@1.0.0-preview-ea0a8c22f
@metamask-previews/shield-controller@5.1.3-preview-ea0a8c22f
@metamask-previews/signature-controller@39.2.9-preview-ea0a8c22f
@metamask-previews/smart-transactions-controller@25.0.2-preview-ea0a8c22f
@metamask-previews/snap-account-service@2.1.1-preview-ea0a8c22f
@metamask-previews/social-controllers@2.7.0-preview-ea0a8c22f
@metamask-previews/solana-test-validator-up@1.0.0-preview-ea0a8c22f
@metamask-previews/stellar-quickstart-up@0.0.0-preview-ea0a8c22f
@metamask-previews/storage-service@1.0.2-preview-ea0a8c22f
@metamask-previews/subscription-controller@6.2.1-preview-ea0a8c22f
@metamask-previews/transaction-controller@69.4.0-preview-ea0a8c22f
@metamask-previews/transaction-pay-controller@26.1.1-preview-ea0a8c22f
@metamask-previews/user-operation-controller@41.2.8-preview-ea0a8c22f
@metamask-previews/wallet@9.0.0-preview-ea0a8c22f
@metamask-previews/wallet-cli@0.0.0-preview-ea0a8c22f

… URL from environment

Move the widened-path default redirect ("fake callback") URL derivation into
the controller instead of accepting a client-injected URL callback.

- Add `getDefaultRedirectCallbackUrl(environment)` mapping each `RampsEnvironment`
  to its `on-ramp-content` fake-callback host (dev uses `on-ramp.dev-api`, which
  has no content deployment; local uses `localhost:3000`).
- Replace the `getDefaultRedirectUrl` callback option on `RampsControllerOptions`
  with an `environment` option (defaults to Staging, matching `RampsService`);
  the widened quote path derives the default from it.

BREAKING: `getDefaultRedirectUrl` is removed from `RampsControllerOptions`;
clients pass `environment` instead of injecting a URL callback. Behaviour is
preserved: an explicit caller `redirectUrl` still wins, and the native-only
(flag-off) path still injects nothing.
Make RampsControllerOptions.environment required so a production consumer
cannot silently fall back to the Staging fake-callback after dropping
getDefaultRedirectUrl. Document that the same environment must be used by
RampsService and callback-matching UI.
…psService

Make RampsService the single runtime owner of the Headless Buy fake-callback
URL. RampsController asks for it through a new messenger action on the widened
path when the caller omits redirectUrl, instead of taking a duplicated
environment option or a client URL callback.

- Export getDefaultRedirectCallbackUrl(environment) as the canonical map.
- Expose RampsService:getDefaultRedirectCallbackUrl (sync; baseUrlOverride does
  not apply, because prod/staging callbacks use on-ramp-content hosts).
- Remove getDefaultRedirectUrl and the temporary environment constructor option.
- Pin the missing-delegation contract: undelegated hosts reject the whole
  getQuotes call, including MM Pay fiat quoting.

BREAKING: hosts must delegate the new action (or spread
RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS) and stop passing getDefaultRedirectUrl.
@saustrie-consensys saustrie-consensys self-assigned this Aug 3, 2026
@saustrie-consensys
saustrie-consensys marked this pull request as ready for review August 3, 2026 15:19
@saustrie-consensys
saustrie-consensys requested review from a team as code owners August 3, 2026 15:19
@saustrie-consensys
saustrie-consensys added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit e7cb039 Aug 3, 2026
50 checks passed
@saustrie-consensys
saustrie-consensys deleted the tram-3757-redirect-url branch August 3, 2026 15:53
@saustrie-consensys saustrie-consensys mentioned this pull request Aug 4, 2026
4 tasks
pull Bot pushed a commit to Reality2byte/core that referenced this pull request Aug 4, 2026
## Explanation

Automated release bump created with `yarn create-release-branch` for:

- `@metamask/ramps-controller` `18.0.1` to `19.0.0` (major). Unreleased
includes breaking changes from MetaMask#9752 (remove `getDefaultRedirectUrl`
from `RampsControllerOptions`; require
`RampsService:getDefaultRedirectCallbackUrl` delegation) plus the new
`setSelectedProviderForAsset` API and `providerServesAsset` fix from
MetaMask#9759.
- `@metamask/transaction-pay-controller` `26.2.0` to `26.2.1` (patch).
Included as a direct dependent of the major bump so its
`@metamask/ramps-controller` range moves to `^19.0.0`. Also publishes
the pending `@metamask/network-controller` bump.

SemVer: major is required because of the MetaMask#9752 BREAKING entries in
Unreleased; a minor would be wrong even though MetaMask#9759 alone would have
been a minor.

## References

- Related to MetaMask#9759 (`setSelectedProviderForAsset` and
`providerServesAsset` fix)
- Related to MetaMask#9752 (Headless Buy default redirect URL sourced from
`RampsService`; breaking for hosts)
- Consumer mobile adoption for MetaMask#9759: MetaMask/metamask-mobile#34195
- Breaking-change consumer note from MetaMask#9752: hosts must drop
`getDefaultRedirectUrl` and delegate
`RampsService:getDefaultRedirectCallbackUrl` (or spread
`RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS`)

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Low direct code risk in this diff, but shipping ramps-controller
19.0.0 forces consumer migrations (messenger delegation, dropped
`getDefaultRedirectUrl`) and can break MM Pay fiat quoting if hosts are
not updated.
> 
> **Overview**
> This is an **automated release cut** (no application code in the
diff): it finalizes versions and changelogs so npm consumers pick up
ramps work that landed in earlier PRs.
> 
> **`@metamask/ramps-controller` `19.0.0` (major)** moves Unreleased
notes into `[19.0.0]`. Hosts upgrading get **breaking** Headless Buy
redirect wiring: `getDefaultRedirectUrl` is removed from
`RampsControllerOptions`, widened `getQuotes` paths must delegate
**`RampsService:getDefaultRedirectCallbackUrl`**, and defaults come from
**`RampsService` / `getDefaultRedirectCallbackUrl(environment)`**. The
release also documents **`setSelectedProviderForAsset`** plus a
**`providerServesAsset`** fix (map values must be `true`).
> 
> **`@metamask/transaction-pay-controller` `26.2.1` (patch)** bumps
**`@metamask/ramps-controller`** to `^19.0.0` as a direct dependent and
records a pending **`@metamask/network-controller`** `^35.0.1` bump. The
root monorepo version becomes **`1172.0.0`**; **`yarn.lock`** is updated
accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
277ec22. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
pull Bot pushed a commit to Reality2byte/metamask-mobile that referenced this pull request Aug 4, 2026
…Mask#34207)

<!--
Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until this PR meets the canonical
Definition of Ready For Review in `docs/readme/ready-for-review.md`.
-->

## **Description**

<!-- mms-check: type=text required=true -->

Adopts the TRAM-3757 core change from MetaMask/core#9752 so Headless Buy
and UB2 share one finish-line (fake-callback) URL derivation.

- Bumps `@metamask/ramps-controller` to the stable published `^19.0.0`
release.
- Removes the client `getDefaultRedirectUrl` injection from
`ramps-controller-init.ts`. Core now supplies the widened-path default
through `RampsService:getDefaultRedirectCallbackUrl`.
- Spreads `RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS` in the controller
messenger so the new action cannot be forgotten on future upgrades.
- Rewrites `getRampCallbackBaseUrl()` as
`getDefaultRedirectCallbackUrl(getRampsEnvironment())`, deleting the
duplicated host table. BuildQuote, Continue rewrite, Checkout completion
matching, and the controller default now all use the same environment
source (`RAMPS_ENVIRONMENT`, then `METAMASK_ENVIRONMENT`).

## **Changelog**

<!-- mms-check: type=changelog required=true blocking=true -->

CHANGELOG entry: null

## **Related issues**

<!-- mms-check: type=issue-link required=true -->

Fixes: TRAM-3757
Refs: MetaMask/core#9752

## **Manual testing steps**

<!-- mms-check: type=manual-testing required=true -->

N/A - unit-covered wiring and package bump only. Covered by unit tests
for `getRampCallbackBaseUrl` (parity with
`getDefaultRedirectCallbackUrl(getRampsEnvironment())`, including
`RAMPS_ENVIRONMENT` override), `ramps-controller-init`, and messenger
construction.

## **Screenshots/Recordings**

<!-- mms-check: type=screenshot required=true -->

N/A - no user-visible UI change; wiring/package bump only.

### **Before**

N/A

### **After**

N/A, simply proving that UB2 still works.


https://github.com/user-attachments/assets/61bf61fb-765c-4fe1-923c-3ce03d4e5d1e



## **Pre-merge author checklist**

<!-- mms-check: type=checklist required=true -->

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

#### Performance checks (if applicable)

- [ ] I've tested on Android
  - Ideally on a mid-range device; emulator is acceptable
- [ ] I've tested with a power user scenario
- Use these [power-user
SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93)
to import wallets with many accounts and tokens
- [ ] I've instrumented key operations with Sentry traces for production
performance metrics
- See [`trace()`](/app/util/trace.ts) for usage and
[`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274)
for an example

For performance guidelines and tooling, see the [Performance
Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers).

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes ramp buy/checkout redirect URL resolution for headless and UB2
flows; behavior should match prior mapping but depends on core v19 and
messenger delegation being correct.
> 
> **Overview**
> Bumps **`@metamask/ramps-controller`** to **^19.0.0** (TRAM-3757 /
core#9752) so the widened Headless Buy quote path gets its default
redirect from core instead of the mobile client.
> 
> **`getRampCallbackBaseUrl()`** no longer maintains a local host switch
on `METAMASK_ENVIRONMENT`; it delegates to
**`getDefaultRedirectCallbackUrl(getRampsEnvironment())`**, aligning UB2
BuildQuote, checkout completion, and Continue rewrite with the same env
source (`RAMPS_ENVIRONMENT`, then `METAMASK_ENVIRONMENT`).
**`ramps-controller-init`** drops the **`getDefaultRedirectUrl`**
injection into **`RampsController`**.
> 
> The ramps controller messenger now spreads
**`RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS`** instead of a
hand-maintained action list, so
**`RampsService:getDefaultRedirectCallbackUrl`** stays delegated on
upgrades. Tests assert parity with core and **`RAMPS_ENVIRONMENT`**
override behavior.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
721b70e. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants